#include "../pch.h"

namespace BFX
{

REFXMLNodeMap::REFXMLNodeMap(REFXMLNode* pParent)
{
	m_pParent = pParent;
	m_pNodes = new REFXMLNodeArray();
}

REFXMLNodeMap::~REFXMLNodeMap()
{
}

// Retrieves a node specified by name.
REFXMLNode* REFXMLNodeMap::GetNamedItem(const UniString& strName) const
{
	int iOffset = FindNodeOffset(strName);
	if (iOffset >= 0)
	{
		return m_pNodes->GetAt(iOffset);
	}
	return NULL;
}

// Retrieves a node specified by LocalName and NamespaceURI.
REFXMLNode* REFXMLNodeMap::GetNamedItem(const UniString& strLocalName, const UniString& strNamespaceURI) const
{
	int iOffset = FindNodeOffset(strLocalName, strNamespaceURI);
	if (iOffset >= 0)
	{
		return m_pNodes->GetAt(iOffset);
	}
	return NULL;
}

// Adds a node using its Name property
REFXMLNode* REFXMLNodeMap::SetNamedItem(REFXMLNode* pNode)
{
	if (pNode == NULL)
		return NULL;

	int iOffset = FindNodeOffset(pNode->GetLocalName(), pNode->GetNamespaceURI());
	if (iOffset == -1)
	{
		AddNode(pNode);
		return NULL;
	}
	else
	{
		return ReplaceNodeAt(iOffset, pNode);
	}
}

// Removes the node specified by name.
REFXMLNode* REFXMLNodeMap::RemoveNamedItem(const UniString& strName)
{
	int iOffset = FindNodeOffset(strName);
	if (iOffset >= 0)
	{
		return RemoveNodeAt(iOffset);
	}
	return NULL;
}

// Removes a node specified by local name and namespace URI.
REFXMLNode* REFXMLNodeMap::RemoveNamedItem(const UniString& strLocalName, const UniString& strNamespaceURI)
{
	int iOffset = FindNodeOffset(strLocalName, strNamespaceURI);
	if (iOffset >= 0)
	{
		return RemoveNodeAt(iOffset);
	}
	return NULL;
}

// Gets the number of nodes in this collection.
int REFXMLNodeMap::GetCount() const
{
	return (m_pNodes != NULL) ? m_pNodes->GetSize() : 0;
}

// Retrieves the node at the specified index in this collection.
REFXMLNode* REFXMLNodeMap::GetNode(int iIndex) const
{
	if (iIndex < 0 || iIndex >= GetCount())
		return NULL;
	return m_pNodes->GetAt(iIndex);
}

int REFXMLNodeMap::FindNodeOffset(const UniString& strName) const
{
	BFX_ASSERT(m_pNodes != NULL);

	for (int i = 0; i < GetCount(); i++)
	{
		REFXMLNode* pNode = m_pNodes->GetAt(i);
		if (strName == pNode->GetName())
			return i;
	}
	return -1;
}

int REFXMLNodeMap::FindNodeOffset(const UniString& strLocalName, const UniString& strNamespaceURI) const
{
	BFX_ASSERT(m_pNodes != NULL);

	for (int i = 0; i < GetCount(); i++)
	{
		REFXMLNode* pNode = m_pNodes->GetAt(i);
		if (strLocalName == pNode->GetLocalName() && strNamespaceURI == pNode->GetNamespaceURI())
			return i;
	}
	return -1;
}

REFXMLNode* REFXMLNodeMap::ReplaceNodeAt(int i, REFXMLNode* pNode)
{
	REFXMLNode* pOldNode = RemoveNodeAt(i);

	InsertNodeAt(i, pNode);
	return pOldNode;
}

REFXMLNode* REFXMLNodeMap::RemoveNodeAt(int i)
{
	BFX_ASSERT(i >= 0 && m_pNodes != NULL && m_pNodes->GetSize() > i);

	REFXMLNode* pOldNode = m_pNodes->GetAt(i);
	pOldNode->Autorelease();

	m_pNodes->RemoveAt(i);
	pOldNode->SetParent(NULL);
	return pOldNode;
}

REFXMLNode* REFXMLNodeMap::InsertNodeAt(int i, REFXMLNode* pNode)
{
	BFX_ASSERT(i >= 0 && m_pNodes != NULL && m_pNodes->GetSize() > i);

	m_pNodes->InsertAt(i, pNode);
	pNode->SetParent(m_pParent);
	return pNode;
}

REFXMLNode* REFXMLNodeMap::AddNode(REFXMLNode* pNode)
{
	BFX_ASSERT(m_pNodes != NULL);

	m_pNodes->Add(pNode);
	pNode->SetParent(m_pParent);
	return pNode;
}

}	//	namespace BFX
